package com.hhsjdesign.dynamicui.asm.v3

import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes

//方法访问者
class InjectMethodVisitor extends MethodVisitor {

    String methodName
    ScanSettingV3 scanSettingV3

    InjectMethodVisitor(ScanSettingV3 extension, int  api, MethodVisitor mv, String methodName) {
        super(api, mv)
        this.scanSettingV3 = extension
        this.methodName = methodName
    }

    void asm2(String name) {
        String className = name
        println "类名： ${className}"
        className = name.replaceAll("/", ".")
        mv.visitVarInsn(Opcodes.ALOAD, 1)

        //Class.forName方法的参数1
        mv.visitLdcInsn(className)
        //调用forName方法
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false)
        //方法名，执行Class.getDeclaredMethod方法，该方法有2个参数，1个是string，方法名，一个是Class数组
        mv.visitLdcInsn(methodName)
        //创建getDeclaredMethod的可变数组
        mv.visitInsn(Opcodes.ICONST_0)
        mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class")
        //执行getDeclaredMethod
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getDeclaredMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false)
        //方法invoke,传入的是null,和可变数据
        mv.visitInsn(Opcodes.ACONST_NULL)
        //invoke的可变数组
        mv.visitInsn(Opcodes.ICONST_0)
        mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object")
        //执行invoke方法
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false)
        //强转
        mv.visitTypeInsn(Opcodes.CHECKCAST, "java/util/Map")
        //执行map的putAll
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Map", "putAll", "(Ljava/util/Map;)V", true)
    }

    /**
     * 在操作保存result 这个变量后面，紧接着开始插入目标代码
     * @param opcode
     * @param i
     */
    @Override
    void visitVarInsn(int opcode, int i) {
        super.visitVarInsn(opcode, i)

        //插入点是保存第一个变量的时候
        if (opcode == Opcodes.ASTORE && i == 1) {
            if (methodName == ScanSettingV3.GENERATE_TO_METHOD_NAME1) {
                if (scanSettingV3.classList.size() > 0) {
                    scanSettingV3.classList.each { generateClassName ->
                        asm2(generateClassName)
                    }
                }
            }

            if (methodName == ScanSettingV3.GENERATE_TO_METHOD_NAME2) {
                if (scanSettingV3.classList.size() > 0)
                    scanSettingV3.classList.each { generateClassName ->
                        asm2(generateClassName)
                    }
            }

            if (methodName == ScanSettingV3.GENERATE_TO_METHOD_NAME3) {
                if (scanSettingV3.classList.size() > 0)
                    scanSettingV3.classList.each { generateClassName ->
                        asm2(generateClassName)
                    }
            }

            if (methodName == ScanSettingV3.GENERATE_TO_METHOD_NAME4) {
                if (scanSettingV3.classList.size() > 0)
                    scanSettingV3.classList.each { generateClassName ->
                        asm2(generateClassName)
                    }
            }

            if (methodName == ScanSettingV3.GENERATE_TO_METHOD_NAME5) {
                if (scanSettingV3.classList.size() > 0)
                    scanSettingV3.classList.each { generateClassName ->
                        asm2(generateClassName)
                    }
            }

            if (methodName == ScanSettingV3.GENERATE_TO_METHOD_NAME6) {
                if (scanSettingV3.classList.size() > 0)
                    scanSettingV3.classList.each { generateClassName ->
                        asm2(generateClassName)
                    }
            }

            if (methodName == ScanSettingV3.GENERATE_TO_METHOD_NAME7) {
                if (scanSettingV3.classList.size() > 0)
                    scanSettingV3.classList.each { generateClassName ->
                        asm2(generateClassName)
                    }
            }
        }
    }

    @Override
    void visitMaxs(int maxStack, int maxLocals) {
        super.visitMaxs(maxStack + 2, maxLocals)
    }

}
